home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
listings
/
v_02_10
/
2n10062a
< prev
next >
Wrap
Text File
|
1991-07-15
|
17KB
|
617 lines
COMMENT ~
---------------------------------------------------------
LISTING 1
File: breakout.asm
This module contains routines necessary to enable
Ctrl-Break to "break out" of infinite loops. A user
supplied clean up routine may be specified if necessary.
MASM 5.1/TASM 2.0 - C callable installation &
de-installation functions.
Language & memory model independant. Change the .model
directive as needed.
Author: David Burki
---------------------------------------------------------
END OF COMMENT ~
title BREAKOUT.ASM
page 57,132
% .model m_model, lang
; ---- MACROS and EQUATES ----
;macro to simulate an interrupt so the interrupt returns
;to the instruction immediately following the call
sim_int macro num
pushf
call cs:orig_&num
endm
;macro to push selected registers
apush macro a,b,c,d,e,f,g,h
irp x,<a,b,c,d,e,f,g,h>
ifnb <x>
push x
endif
endm
endm
;macro to pop selected registers
apop macro a,b,c,d,e,f,g,h
irp x,<h,g,f,e,d,c,b,a>
ifnb <x>
pop x
endif
endm
endm
;macro to install a replacement vector
; -- assumes that ds = code seg of replacing function
; -- all var names used to save original vector must be
; 2 characters long plus a training "h" (i.e. for
; int 8h "orig_08h")
install_vector macro vector_num,function_name
mov ax,35&vector_num
int 21h
mov word ptr orig_&vector_num,bx
mov word ptr orig_&vector_num+2,es
lea dx,function_name
mov ax,25&vector_num
int 21h
endm
;macro to un-install a replaced vector
; -- all var names used to save original vector must be
; 2 characters long plus a training "h" (i.e. for
; int 8h "orig_08h")
restore_vector macro replaced_vector
lds dx,cs:orig_&replaced_vector
mov ax,25&replaced_vector
int 21h
endm
; segment and offset of the BIOS break flag
BIOS_SEG equ 40h
BREAK_FLAG_OFF equ 71h
; ---- CODE ----
.code
; declare externally visible functions
public insure, cancel
; NOTE: all variables used here are part of the code
; segment so the interrupt routines can have easy
; access to them
; --- storage for the address of the InDOS flag
indos_addr dd 0
; --- storage for the address of the critical error flag
critter_addr dd 0
; --- storage for the version of dos
dos_major_version db 0
dos_minor_version db 0
; --- flag indicating disk i/o in progress
busy_flag db 0
; --- far pointer to clean up routine
exit_routine dd 0
; --- storage for original addresses of intercepted
; interrupt vectors.
orig_08h dd 0
orig_1bh dd 0
orig_13h dd 0
orig_25h dd 0
orig_26h dd 0
; --- storage for the segment addr of the psp of process
; that asked for insurance - if zero, insurance isn't
; in effect
insured_psp dw 0
; --- flag if still processing in int 8h
in_already db 0
; --- interrupted program's SS & SP
save_ss dw 0
save_sp dw 0
; --- original C stack segment
installer_ss dw 0
installer_sp dw 0
; --- local stack while in int_8h_handler
my_stack dw 256 dup(0)
stack_top label word
assume ds:@curseg, es:nothing
;---------------------------------------------------------
; GET_DOS_VERSION()
; Obtain the version & revision of DOS. Store the version
; in the variable "dos_major_version" and the revision in
; the variable "dos_minor_version". Both variables are code
; segment variables.
;
; Returns:
; AL - dos minor version number
; AH - dos major version number
;---------------------------------------------------------
public get_dos_version
get_dos_version proc
mov ah,30h
int 21h
mov cs:dos_major_version,al
mov cs:dos_minor_version,ah
ret
get_dos_version endp
;---------------------------------------------------------
; GET_CRITICAL_ERROR_ADDR()
; This function obtains & saves the address of the
; critical error flag. For DOS versions 3+, the critical
; error flag is the byte just before the InDOS flag. For
; DOS 2.x, it's the byte just after.
;
; NOTE: get_dos_version() must be called before this
; function
;
; NOTE: For COMPAQ DOS version 3.x, the critical error
; flag is located 01aah bytes BEFORE the InDOS flag.
;
; Trashes: AX
;---------------------------------------------------------
public get_critical_error_addr
get_critical_error_addr proc USES ES BX
; --- get the address of the InDOS flag
mov ah,34h
int 21h
; --- dos 3.x or better use byte before InDOS
cmp byte ptr cs:dos_major_version,3
jge byte_before ;good_version
; --- dos 2.x, use byte after InDOS flag
inc bx
jmp store_critter_addr
byte_before:
dec bx
store_critter_addr:
; --- save the address & return success
mov word ptr cs:critter_addr,bx
mov word ptr cs:critter_addr+2,es
ret
get_critical_error_addr endp
;---------------------------------------------------------
; GET_INDOS_ADDR()
; Uses the undocumented (but well known) function 34h of
; INT 21h to obtain a far pointer to the "InDOS" flag.
; Stores the address of the flag in the code segment
; variable "indos_addr".
;
; Trashes AX
;---------------------------------------------------------
public get_indos_addr
get_indos_addr proc USES ES BX
; --- get the address
mov ah,34h
int 21h
; --- save address in cs referenced variable
mov word ptr cs:indos_addr,bx
mov word ptr cs:indos_addr+2,es
ret
get_indos_addr endp
;---------------------------------------------------------
; CHECK_CRITTER_FLAG()
; Examine the undocumented "critical error" flag to
; determine if a critical error is in progress.
;
; Returns:
; carry clear - A critical error is NOT in progress
; carry set - A critical error is in progress
;---------------------------------------------------------
public check_critter_flag
check_critter_flag proc USES AX DS SI
; --- ds:si <- address of critter flag
lds si,dword ptr cs:critter_addr
; --- check critter flag = zero
lodsb
or al,al
jz no_critter
; --- critter flag not zero, return carry set
stc
jmp critter_exit
; --- critter flag zero, return carry clear
no_critter:
clc
critter_exit:
ret
check_critter_flag endp
;---------------------------------------------------------
; CHECK_INDOS_FLAG()
; Examine the undocumented "InDOS" flag to determine if
; non-rentrant DOS functions are currently executing.
;
; Returns:
; carry clear - InDOS flag is zero.
; carry set - InDOS flag is non-zero.
;---------------------------------------------------------
public check_indos_flag
check_indos_flag proc USES AX DS SI
; --- ds:si <-- addr of InDOS flag, then load al with
; the byte at that address
lds si,dword ptr cs:indos_addr
lodsb
; --- indos flag equal zero, DOS is stable
or al,al
jz dos_stable
; --- no, set carry & return
stc
jmp indos_exit
; --- yes, clear carry and return
dos_stable:
clc
indos_exit:
ret
check_indos_flag endp
;---------------------------------------------------------
; CHECK_BREAK_BIT()
; This function examines the BIOS Break Flag (bit 7 of
; the byte at 40:71).
;
; Returns:
; carry clear - Break Flag is clear.
; carry set - Break Flag is set.
;---------------------------------------------------------
check_break_bit